package com.huawei.boss.monit;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

/**
 * 定时监控特定资源并执行工作任务进行更新操作
 * @author c00170351
 */
public class MonitTask {
    private static final Logger LOG = LoggerFactory.getLogger(MonitTask.class);
    private RunnableTask task;
    private Resource resource;
    private long checkInterval = -1;
    private long lastModified = -1;
    private Thread taskThread;
    private boolean exitWhenException = false;

    public boolean start() throws MonitException {
        Assert.notNull(task, "工作任务不能为空!");
        Assert.notNull(resource, "监控对象不能为空!");
        Assert.isTrue(checkInterval > 0, "工作线程工作间隔时间不能小于0");

        if (taskThread != null && taskThread.isAlive()) {
            LOG.warn("工作线程不能重复启动!");
            return false;
        }

        //启动工作线程
        taskThread = new MonitThread();
        taskThread.start();
        return true;
    }

    public boolean stop() {
        if (taskThread == null || !taskThread.isAlive()) {
            LOG.warn("工作线程没有启动或者已经退出!");
            return false;
        }

        //已经发送中断请求
        taskThread.interrupt();
        return true;
    }

    private boolean checkModified() throws IOException {
        if (lastModified < 0 || resource.lastModified() > lastModified) {
            lastModified = resource.lastModified();
            LOG.debug("监控对象出现更新,lastModified={}", lastModified);
            return true;
        } else {
            LOG.debug("监控对象没有更新,lastModified={}", lastModified);
            return false;
        }
    }
    
    public void setExitWhenException(boolean exitWhenException) {
        this.exitWhenException = exitWhenException;
    }

    public void setTask(RunnableTask task) {
        this.task = task;
    }

    public void setResource(Resource resource) {
        this.resource = resource;
    }

    public void setCheckInterval(long checkInterval) {
        this.checkInterval = checkInterval;
    }

    private class MonitThread extends Thread {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                try {
                    //检测是否需要执行工作任务进行更新
                    if (checkModified()) {
                        task.run();
                    }
                } catch (Exception ex) {
                    String errorMessage = "执行工作任务" + task.getName() + "出现异常!";
                    LOG.warn(errorMessage, ex);
                    if (exitWhenException) {
                        throw new MonitException(errorMessage, ex);
                    }
                }

                try {
                    //线程开始休眠
                    Thread.sleep(checkInterval);
                } catch (InterruptedException ex) {
                    //便于工作线程退出
                    LOG.warn("执行工作任务" + task.getName() + "的线程" + Thread.currentThread().getName() + "即将退出!");
                    Thread.currentThread().interrupt();
                }
            }
            LOG.warn("执行工作任务" + task.getName() + "的线程" + Thread.currentThread().getName() + "退出!");
        }
    }
}
